#pragma once

#include <Arduino.h>
#include <U8g2lib.h>
#include <functional>
#include <string>
#include <WIFI.h>
#include <WIFIClient.h>

#include "Button.hpp"
#include "Rocker_Button.hpp"

extern U8G2_SSD1306_128X64_NONAME_F_HW_I2C oled;
extern Buttons<5> buttons;
extern const char* ip;
extern const short port;
extern WiFiClient client;
extern const char* password;
extern Rocker_Button x_button;
extern Rocker_Button y_button;

class Start_Menu
{
public:
    void start(const char* show)
    {
        oled.clearBuffer();

        oled.setCursor(50, 25);
        oled.print(show);
        oled.setCursor(32, 40);
        oled.print("please enter");

        oled.sendBuffer();

        buttons.waiting();
    }
};

class Connect_Wifi_Menu
{
public:
    // 选择wifi连接
    void choice()
    {
        WiFi.mode(WIFI_MODE_STA);

        scan_wifi();

        while (!WiFi.isConnected())
        {
            oled.clearBuffer();

            oled.setCursor(5, 10);
            oled.print(">>>");

            for (int i = 0; i < _show_max; ++i)
            {
                if (_index + i < _wifi_nums)
                    show_ssid(_index, i);
            }
            
            oled.sendBuffer();
            button();
        }
    }
private:
    void scan_wifi()
    {
        _index = 0;
        _wifi_nums = WiFi.scanNetworks();
        for (int i = 0; i < 3; ++i)
        {
            oled.clearBuffer();
            
            oled.setCursor(35, 25);
            oled.print("scan success");
            oled.setCursor(35, 40);
            oled.print("please enter");

            oled.sendBuffer();
            delay(300);
        }
    }
    void show_ssid(int index, int n)
    {
        oled.setCursor(30, 10 + n * 18);
        oled.print(WiFi.SSID(index + n).c_str());
    }
    void connect()
    {
        // 尝试连接三次WiFi
        for (int i = 0; i < 3 && WiFi.status() != WL_CONNECTED; ++i)
        {
            oled.clearBuffer();
            WiFi.begin(WiFi.SSID(_index).c_str(), password);

            oled.setCursor(40, 25);
            oled.print("connect wifi");

            oled.sendBuffer();
            delay(500);
        }

        // 显示连接结果
        oled.clearBuffer();

        if (WiFi.status() != WL_CONNECTED)
        {
            oled.setCursor(40, 25);
            oled.print("connect fail");
        }
        else
        {
            // wifi连接成功后，向服务端发起tcp连接
            if (!client.connect(ip, port))
            {
                oled.setCursor(40, 25);
                oled.print("connect fail");
                WiFi.disconnect();
            }
            else
            {
                oled.setCursor(32, 25);
                oled.print("connect success");
            }
        }
        oled.setCursor(36, 40);
        oled.print("please enter");
        
        oled.sendBuffer();

        buttons.waiting();
    }
    void button()
    {
        switch (buttons.get_value())
        {
        case 0 :
            connect();
            break;
        case 1 :
            ++_index;
            if (_index >= _wifi_nums)
                --_index;
            break;
        case 2 :
            _index--;
            if (_index < 0)
                _index++;
            break;
        case 3 :
            scan_wifi();
        default :
            break;
        }
    }
private:
    int _index = 0;
    int _wifi_nums = 0;
    const int _show_max = 4;
};

class Remote_Control_Menu
{
public:
    int remote_control()
    {
        oled.clearBuffer();

        // 显示摇杆位置
        int cx = map(x_button.get_value(), x_button._value_min, x_button._value_max, 5, 95);
        int cy = map(y_button.get_value(), y_button._value_min, y_button._value_max, 5, 55);

        oled.drawLine(5, 32, 95, 32);     // x
        oled.drawLine(50, 7, 50, 57);     // y
        oled.drawDisc(cx, cy, 3);

        // 显示档位
        oled.setCursor(100, 10);
        oled.print(_info);
        // 定速巡航
        if (_speed)
        {
            oled.setCursor(99, 25);
            oled.print("speed");
        }

        oled.sendBuffer();
        return button();
    }
private:
    int button()
    {
        switch (buttons.get_value())
        {
        case 1 :
            _level++;
            if (_level > _level_max)
                _level = _level_max;
            _info[4] = '0' + _level;
            break;
        case 2 :
            _level--;
            if (_level < 0)
                _level = 0;
            _info[4] = '0' + _level;
            break;
        case 3 :
            _speed = !_speed;
            break;
        case 4 :
            return 0;
        default :
            break;
        }
        return 3;
    }
public:
    bool _speed =  false;
    int _level = 0;
private:
    char _info[10] = "lv: 0";
    const int _level_max = 3;
};

class Menu : public Start_Menu, public Connect_Wifi_Menu, public Remote_Control_Menu
{
public:
    void restart()
    {
        _menu_index = 0;
        client.stop();
        WiFi.disconnect();
    }
    void run()
    {
        switch (_menu_index)
        {
        case 0 :
            restart();
            Start_Menu::start("Welcome");
            ++_menu_index;
        case 1 :
            Connect_Wifi_Menu::choice();
            ++_menu_index;
        case 2 :
            Start_Menu::start("Start");
            ++_menu_index;
        case 3 :
            _menu_index = Remote_Control_Menu::remote_control();
            break;
        default :
            break;
        }
    }
private:
    int _menu_index = 0;
};